import java.util.LinkedList;

/**
 * Snake类表示蛇
 *      一条蛇有多个节点使用LinkedList集合存储Node节点，蛇出生的时候 有6个节点。
 */
public class Snake {
    //蛇的身体
     private int sum;

    public int getSum() {
        return sum;
    }

    public void setSum(int sum) {
        this.sum = sum;
    }

    private LinkedList<Node> body;//创建了一个node类型的集合变量
    //蛇的运动方向,默认向左
    private Direction direction=Direction.LEFT;
    //蛇是否活着
    private boolean isLiving=true;//创建一个真假值，看看蛇是否撞墙，从而控制是否让蛇接着移动，所以这个真假值就是放在move方法执行的判断语句
    //构造方法，在创建Snake对象时执行
    public Snake() {
        //初始化蛇身体
        initSnake();
    }


    //初始化蛇身体
    private void initSnake() {
        //创建集合
        body=new LinkedList<>();//上面只是定义了，这里才是开辟空间进行初始化
        //创建6个节点，添加到集合中
        body.add(new Node(16,20));
        body.add(new Node(17,20));
        body.add(new Node(18,20));
        body.add(new Node(19,20));
        body.add(new Node(20,20));
        body.add(new Node(21,20));
        body.add(new Node(22,20));
        body.add(new Node(23,20));
        body.add(new Node(24,20));
    }

    //蛇会沿着蛇头的方向移动
    //控制蛇移动：在蛇头的运动方向添加一个节点，然后把蛇尾的节点删除
    public void move(){
        if(isLiving){
            //获取蛇头
            Node head = body.getFirst();
            switch (direction){
                case UP:
                    //在蛇头的上边添加一个节点
                    body.addFirst(new Node(head.getX(),head.getY()-1));
                    break;
                case DOWN:
                    body.addFirst(new Node(head.getX(),head.getY()+1));
                    break;
                case LEFT:
                    body.addFirst(new Node(head.getX()-1,head.getY()));
                    break;
                case RIGHT:
                    body.addFirst(new Node(head.getX()+1,head.getY()));
                    break;
            }
            //删除最后的节点
            body.removeLast();//一定要注意是调用了哪一个类的方法，这里的话是调用了body这个对象里面的一个方法，
            // 而body是属于 LinkedList<Node>类型的，所以这里的removelast就是用了linkedlist里面的一个方法

            //判断蛇是否撞墙
            head=body.getFirst();
            if(head.getX()<0||head.getY()<0||head.getX()>=40||head.getY()>=40){
                isLiving=false;
            }

            //判断蛇是否碰到自己的身体
            for (int i = 1; i < body.size(); i++) {//这里的body.size和body.get都是调用了linkedlist这个类的方法
                Node node = body.get(i);
                if(head.getX()==node.getX()&&head.getY()==node.getY()){//在蛇下一次运动之前，遍历蛇的每一个节点，将每一个节点与这头蛇此时的
                    //头节点进行比较，看看是否相同，相同就是撞到了蛇的身体，这个时候就得令isLiving的值变成假，让蛇不再动，游戏结束
                    isLiving=false;
                }
            }
        }
    }


    public LinkedList<Node> getBody() {
        return body;
    }

    public void setBody(LinkedList<Node> body) {
        this.body = body;
    }

    public Direction getDirection() {//在这里创建了direction方向变量的一个get和set的方法
        //因为你在move方法控制蛇移动时的方向是根据direction变量的值来移动的，然后在主类里面有一个
        //键盘输入来改变direction的方法，因为在snake里面设置的这个变量是privite类型的，所以要专门
        //设个方法来获取这里的direction 变量值
        return direction;
    }

    public boolean isLiving() {
        return isLiving;
    }

    public void setDirection(Direction direction) {
        this.direction = direction;
    }

    //吃食物：沿着蛇头的移动方向添加一个节点
    public void eat(Node food) {
        //获取蛇头
        Node head = body.getFirst();
        switch (direction){//因为这里跟前面的重复了，所以后续可以把这一整个部分弄成一个方法，简化代码
            case UP:
                //在蛇头的上边添加一个节点
                body.addFirst(new Node(head.getX(),head.getY()-1));
                break;
            case DOWN:
                body.addFirst(new Node(head.getX(),head.getY()+1));
                break;
            case LEFT:
                body.addFirst(new Node(head.getX()-1,head.getY()));
                break;
            case RIGHT:
                body.addFirst(new Node(head.getX()+1,head.getY()));
                break;
        }
    }
}